package com.ticket.system.service.impl;

import com.google.common.collect.Lists;
import com.ticket.common.constant.CacheConstants;
import com.ticket.common.core.domain.entity.SysDept;
import com.ticket.common.core.domain.model.LoginUser;
import com.ticket.common.core.redis.RedisCache;
import com.ticket.common.exception.base.BaseException;
import com.ticket.common.utils.Const;
import com.ticket.common.utils.DateUtils;
import com.ticket.common.utils.PageUtils;
import com.ticket.common.utils.SecurityUtils;
import com.ticket.system.domain.TYanchuClassify;
import com.ticket.system.domain.YanchuPerform;
import com.ticket.system.domain.YanchuSession;
import com.ticket.system.domain.vo.*;
import com.ticket.system.mapper.*;
import com.ticket.system.service.IYanchuPerformService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 演出Service业务层处理
 * 
 * @author ruoyi
 * @date 2023-09-27
 */
@Service
public class YanchuPerformServiceImpl implements IYanchuPerformService 
{
    private static final Logger logger = LoggerFactory.getLogger(YanchuPerformServiceImpl.class);
    @Autowired
    private YanchuPerformMapper yanchuPerformMapper;

    @Autowired
    private YanchuSessionMapper yanchuSessionMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private TYanchuClassifyMapper tYanchuClassifyMapper;
    @Autowired
    private SysDeptMapper deptMapper;
    @Autowired
    private YanchuTicketPriceMapper yanchuTicketPriceMapper;
    @Autowired
    private YanchuEvaluateMapper evaluateMapper;
    /**
     * 查询演出
     * 
     * @param id 演出主键
     * @return 演出
     */
    @Override
    public YanchuPerform selectYanchuPerformById(Long id)
    {
        YanchuPerform perform = yanchuPerformMapper.selectYanchuPerformById(id);
        TYanchuClassify classify = tYanchuClassifyMapper.selectTYanchuClassifyById(perform.getPerformType());
        if (null != classify) {
            perform.setPerformTypeName(classify.getClassifyName());
        }
        SysDept sysDept = deptMapper.selectDeptById(perform.getOperaId());
        if (null != sysDept){
            perform.setOperaName(sysDept.getDeptName());
        }
        List<TicketStatistics> tickets = yanchuSessionMapper.selectTicketTotalList(Collections.singletonList(id));
        if(CollectionUtils.isEmpty(tickets)){
            perform.setType(0);
        }else if (tickets.get(0).getSelledSession()>0){
            perform.setType(2);
        }else if(tickets.get(0).getNoSelledSession()>0 && tickets.get(0).getSelledSession()==0){
            perform.setType(1);
        }else if(tickets.get(0).getEndNum()>0 && tickets.get(0).getSelledSession()==0){
            perform.setType(3);
        }else {
            perform.setType(0);
        }
        return perform;
    }

    /**
     * 查询演出列表
     * 
     * @param yanchuPerform 演出
     * @return 演出
     */
    @Override
    public List<YanchuPerform> selectYanchuPerformList(YanchuPerform yanchuPerform)
    {
        /*LoginUser user = SecurityUtils.getLoginUser();
        if(StringUtils.isEmpty(yanchuPerform.getCreateBy())){
            yanchuPerform.setCreateBy(user.getUserId()+"");
        }*/
        List<YanchuPerform> list = yanchuPerformMapper.selectYanchuPerformList(yanchuPerform);
        TicketStatistics stat = null;
        if(!CollectionUtils.isEmpty(list)){
            List<Long> ids = list.stream().map(YanchuPerform::getId).collect(Collectors.toList());
            List<TicketStatistics> tickets = yanchuSessionMapper.selectTicketTotalList(ids);
            if(CollectionUtils.isNotEmpty(tickets)){
                Map<Long,TicketStatistics> map = tickets.stream().collect(Collectors.toMap(TicketStatistics::getPerformId, a -> a, (k1, k2) -> k1));
                for(YanchuPerform perform:list){
                    stat = map.get(perform.getId());
                    if(null == stat){
                        continue;
                    }
                    perform.setTicketStatistics(stat);
                }
            }
        }
        return list;
    }

    @Override
    public List<YanchuPerform> selectPerformStaticsList(String operaIds,String status,String performTypes,String performName){
        List<YanchuPerform> list = yanchuPerformMapper.selectPerformStaticsList(operaIds,status,performTypes,performName);
        return list;
    }
    @Override
    public List<PerformVo> selectPerformVoList(YanchuPerform yanchuPerform){
        return yanchuPerformMapper.selectPerformVoList(yanchuPerform);
    }

    @Override
    public PerformVo selectPerformVoDetail(Long performId){
        PerformVo performVo = redisCache.getCacheObject(CacheConstants.PERFORM_DETAIL_KEY+performId);
        if(null != performVo){
            return performVo;
        }
        YanchuPerform yanchuPerform = yanchuPerformMapper.selectYanchuPerformById(performId);
        if(null == yanchuPerform){
            return null;
        }
        performVo = new PerformVo();
        performVo.setPerformFrom(yanchuPerform.getPerformFrom());
        performVo.setPerformIntroduction(yanchuPerform.getPerformIntroduction());
        performVo.setPerformName(yanchuPerform.getPerformName());
        performVo.setPerformLength(yanchuPerform.getPerformLength());
        performVo.setPerformPoster(yanchuPerform.getPerformPoster());
        performVo.setSimpleName(yanchuPerform.getSimpleName());
        performVo.setTicketIntroduction(yanchuPerform.getTicketIntroduction());
        performVo.setPerformType(yanchuPerform.getPerformType());
        performVo.setEnterType(yanchuPerform.getEnterType());
        performVo.setReleaseDate(yanchuPerform.getReleaseDate());
        redisCache.setCacheObject(CacheConstants.PERFORM_DETAIL_KEY+performId,performVo,5, TimeUnit.DAYS);
        return performVo;
    }

    /**
     * 新增演出
     * 
     * @param yanchuPerform 演出
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int insertYanchuPerform(YanchuPerform yanchuPerform)
    {
        //校验同一剧院下  演出名称和简称是否重复
        if (this.checkName(null,yanchuPerform.getPerformName(),yanchuPerform.getOperaId())){
            throw new BaseException("演出名称已存在");
        }
        if (this.chechSimple(null,yanchuPerform.getSimpleName(),yanchuPerform.getOperaId())){
            throw new BaseException("演出简称已存在");
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();
        yanchuPerform.setCreateTime(DateUtils.getNowDate());
        yanchuPerform.setCreateBy(loginUser.getUser().getUserId()+"");
        //演出分类表  演出数量加一操作
        tYanchuClassifyMapper.updateByid(yanchuPerform.getPerformType(),1);
        return yanchuPerformMapper.insertYanchuPerform(yanchuPerform);
    }

    /**
     * 校验同一剧院下  演出名称是否重复
     *
     * @param id
     * @param name
     * @param operaId
     * @return
     */
    private Boolean checkName(Long id,String name,Long operaId){
        if (null != id){
            //编辑
            YanchuPerform yanchuPerform = yanchuPerformMapper.selectYanchuPerformById(id);
            if (name.equals(yanchuPerform.getPerformName())){
                return false;
            }
        }
        List<YanchuPerform> perform = yanchuPerformMapper.getPerformByOperaId(operaId);
        if (CollectionUtils.isNotEmpty(perform)){
            List<String> collect = perform.stream().map(YanchuPerform::getPerformName).collect(Collectors.toList());
            if (collect.contains(name)){
                return true;
            }
        }
        return false;
    }

    /**
     * 校验同一剧院下  演出简称是否重复
     *
     * @param id
     * @param simple
     * @param operaId
     * @return
     */
    private Boolean chechSimple(Long id,String simple,Long operaId){
        if (null != id){
            //编辑
            YanchuPerform yanchuPerform = yanchuPerformMapper.selectYanchuPerformById(id);
            if (simple.equals(yanchuPerform.getSimpleName())){
                return false;
            }
        }
        List<YanchuPerform> perform = yanchuPerformMapper.getPerformByOperaId(operaId);
        if (CollectionUtils.isNotEmpty(perform)){
            List<String> collect = perform.stream().map(YanchuPerform::getSimpleName).collect(Collectors.toList());
            if (collect.contains(simple)){
                return true;
            }
        }
        return false;
    }

    /**
     * 修改演出
     * 
     * @param yanchuPerform 演出
     * @return 结果
     */
    @Override
    public int updateYanchuPerform(YanchuPerform yanchuPerform)
    {
        if (this.checkName(yanchuPerform.getId(),yanchuPerform.getPerformName(),yanchuPerform.getOperaId())){
            throw new BaseException("演出名称已存在");
        }
        if (this.chechSimple(yanchuPerform.getId(),yanchuPerform.getSimpleName(),yanchuPerform.getOperaId())){
            throw new BaseException("演出简称已存在");
        }
        redisCache.deleteObject(CacheConstants.PERFORM_DETAIL_KEY+yanchuPerform.getId());
        yanchuPerform.setUpdateTime(DateUtils.getNowDate());
        return yanchuPerformMapper.updateYanchuPerform(yanchuPerform);
    }

    /**
     * 批量删除演出
     * 
     * @param ids 需要删除的演出主键
     * @return 结果
     */
    @Override
    public int deleteYanchuPerformByIds(Long[] ids)
    {
        List<String> keys = Arrays.stream(ids).map(s->CacheConstants.PERFORM_DETAIL_KEY+s).collect(Collectors.toList());
        logger.debug("deleteYanchuPerformByIds keys:{}",keys);
        redisCache.deleteObject(keys);
        return yanchuPerformMapper.deleteYanchuPerformByIds(ids);
    }

    /**
     * 删除演出信息
     * 
     * @param id 演出主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int deleteYanchuPerformById(Long id)
    {
        //演出分类表  演出数量减一操作
        YanchuPerform perform = yanchuPerformMapper.selectYanchuPerformById(id);
        TYanchuClassify classify = tYanchuClassifyMapper.selectTYanchuClassifyById(perform.getPerformType());
        if (Const.ZERO < classify.getClassifyNum()){
            tYanchuClassifyMapper.updateByid(classify.getId(),2);
        }
        redisCache.deleteObject(CacheConstants.PERFORM_DETAIL_KEY+id);
        return yanchuPerformMapper.deleteYanchuPerformById(id);
    }

    /**
     * 海报管理  筛选演出
     *
     * @param operaId
     * @param keyName
     * @return
     */
    @Override
    public List<YanchuPerform> getPerformByPosters(Long operaId, String keyName) {
        YanchuPerform perform = new YanchuPerform();
        perform.setOperaId(operaId);
        perform.setPerformName(keyName);
        perform.setType(1);
        //待销售
        List<YanchuPerform> perOne = yanchuPerformMapper.selectYanchuPerformList(perform);
        perform.setType(2);
        //销售中
        List<YanchuPerform> perTwo = yanchuPerformMapper.selectYanchuPerformList(perform);
        List<YanchuPerform> list = Lists.newArrayList();
        list.addAll(perOne);
        list.addAll(perTwo);
        return list;
    }

    /**
     * 所有演出
     *
     * @return
     */
    @Override
    public List<YanchuPerform> selectYanchuPerformLists(Long operaId) {
        return yanchuPerformMapper.selectYanchuPerformLists(operaId);
    }

    /**
     * 小程序演出列表
     *
     * @param type 1:当前热门演出;2:即将上映演出;3:全部演出
     * @param performType
     * @param operaId
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public List<PerFormAppVO> selectPerformList(List<String> keyName, Long performType, Long operaId,String startTime,String endTime,
                                                Integer type,Integer orderType,Double longitude,Double latitude) {
        List<PerFormAppVO> perFormAppVOS = yanchuPerformMapper.selectPerformList(keyName, performType, operaId, startTime,endTime,
                type,orderType,longitude,latitude);
        if (CollectionUtils.isNotEmpty(perFormAppVOS)){
            List<Long> perIds = perFormAppVOS.stream().map(PerFormAppVO::getPerformId).distinct().collect(Collectors.toList());
            List<YanchuSession> sessions = null;
            if (Const.TWO.equals(type)){
                //待销售
                sessions = yanchuSessionMapper.getToBeSoldPerIds(perIds);
            }else {
               sessions = yanchuSessionMapper.getOnsaleByPerIds(perIds);//销售中
            }
            if (CollectionUtils.isEmpty(sessions)){
                return perFormAppVOS;
            }
            List<Long> sessionIds = sessions.stream().map(YanchuSession::getId).distinct().collect(Collectors.toList());

            PageUtils.startPage();
            perFormAppVOS = yanchuPerformMapper.selectPerformListB(keyName, performType, operaId, startTime,endTime,type,orderType,longitude,latitude,perIds,sessionIds);
            //获取演出价格区间
            List<SessionAndTicket> price = yanchuTicketPriceMapper.getPrice(perIds,sessionIds);
            //时间区间
//            List<SessionAndTicket> time = yanchuSessionMapper.getTime(perIds, sessionIds);
            //剧场
            List<YanchuSession> hallName = yanchuSessionMapper.getHallName(perIds, sessionIds);
            //获取实名标签
//            List<Long> autType = yanchuSessionMapper.getAutType(perIds,sessionIds);
            //获取电子票类标签
            List<Long> isTickets = yanchuSessionMapper.getIsTickets(perIds,sessionIds);
            perFormAppVOS.forEach(p ->{
                if (CollectionUtils.isNotEmpty(price)){
                    price.forEach(c ->{
                        if (p.getPerformId().equals(c.getPerformId())){
                            p.setMaxPrice(c.getMaxPrice());
                            p.setMinPrice(c.getMinPrice());
                        }
                    });
                }
                /*if (CollectionUtils.isNotEmpty(time)){
                    time.forEach(t ->{
                        if (p.getPerformId().equals(t.getPerformId())){
                            p.setStartTime(t.getStartTime());
                            p.setEndTime(t.getEndTime());
                        }
                    });
                }*/
                if (CollectionUtils.isNotEmpty(hallName)){
                    hallName.forEach(h -> {
                        if (p.getPerformId().equals(h.getPerformId())){
                            p.setHallName(h.getSessionName());
                            p.setAutType(h.getAutType());
                        }
                    });
                }
                /*if (CollectionUtils.isNotEmpty(autType)){
                    if (autType.contains(p.getPerformId())){
                        p.setAutType(1);
                    }else {
                        p.setAutType(2);
                    }
                }else {
                    p.setAutType(1);
                }*/
                if (CollectionUtils.isNotEmpty(isTickets)){
                    if (isTickets.contains(p.getPerformId())){
                        p.setIsTickets(1);
                    }else {
                        p.setIsTickets(2);
                    }
                }else {
                    p.setIsTickets(2);
                }
            });
        }
        /*if (Const.THREE.equals(type)){
            perFormAppVOS = perFormAppVOS.stream().sorted(Comparator.comparing(PerFormAppVO::getStartTime)).collect(Collectors.toList());
        }*/
        return perFormAppVOS;
    }

    /**
     * 小程序演出列表
     *
     * @param keyName
     * @param performType 演出类型的id,全部类型时不传参
     * @param operaId
     * @param startTime
     * @param endTime
     * @param orderType 1.距离 2.销量 3.低价 4.好评
     * @param type 1:当前热门演出;2:即将上映演出;3:全部演出
     * @return
     */
    @Override
    public List<PerFormAppVO> selectPerformQueryList(List<String> keyName, Long performType, Long operaId,String startTime,String endTime,Integer type,
                                                     Integer orderType,Double longitude,Double latitude) {
        PageUtils.startPage();
        List<PerFormAppVO> perFormAppVOS = null;
        if(Const.ONE.equals(type)){
            perFormAppVOS = yanchuPerformMapper.selectPerformQueryListBySells(keyName, performType, operaId, startTime,endTime);
        }else if(Const.TWO.equals(type)){
            perFormAppVOS = yanchuPerformMapper.selectPerformQueryListByTime(keyName, performType, operaId, startTime,endTime);
        }else{
            if(Const.ONE.equals(orderType)){
                perFormAppVOS = yanchuPerformMapper.selectPerformQueryListByDist(keyName, performType, operaId, startTime,endTime,
                        longitude,latitude);
            }else if(Const.TWO.equals(orderType)){
                perFormAppVOS = yanchuPerformMapper.selectPerformQueryListBySells(keyName, performType, operaId, startTime,endTime);
            }else if(Const.THREE.equals(orderType)){
                perFormAppVOS = yanchuPerformMapper.selectPerformQueryListByPrice(keyName, performType, operaId, startTime,endTime);
            }else if(Const.FOUR.equals(orderType)){
                perFormAppVOS = yanchuPerformMapper.selectPerformQueryListByEva(keyName, performType, operaId, startTime,endTime);
            }
        }

        return perFormAppVOS;
    }

    @Override
    public YanchuPerform selectMobYanchuPerformById(Long id) {
        Integer type = null;
        List<TicketStatistics> tickets = yanchuSessionMapper.selectTicketTotalList(Collections.singletonList(id));
        if(CollectionUtils.isEmpty(tickets)){
            type = 0;
        }else if (tickets.get(0).getSelledSession()>0){
            type = 2;
        }else if(tickets.get(0).getNoSelledSession()>0 && tickets.get(0).getSelledSession()==0){
            type = 1;
        }else if(tickets.get(0).getEndNum()>0 && tickets.get(0).getSelledSession()==0){
            type = 3;
        }else {
            type = 0;
        }
        /*if (Const.ZERO.equals(type) || Const.THREE.equals(type)){
            throw new BaseException("该演出已下架");
        }*/
        YanchuPerform perform = yanchuPerformMapper.selectYanchuPerformById(id);
        perform.setType(type);
        TYanchuClassify classify = tYanchuClassifyMapper.selectTYanchuClassifyById(perform.getPerformType());
        if (null != classify) {
            perform.setPerformTypeName(classify.getClassifyName());
        }
        SysDept sysDept = deptMapper.selectDeptById(perform.getOperaId());
        if (null != sysDept){
            perform.setOperaName(sysDept.getDeptName());
        }

        List<YanchuSession> sessions = Lists.newArrayList();
        if (Const.ONE.equals(type)){
            //待销售
            sessions = yanchuSessionMapper.getToBeSoldPerIds(Collections.singletonList(id));
        }else if(Const.ZERO.equals(type) ||  Const.THREE.equals(type)) {
            //已下架
            sessions = yanchuSessionMapper.getNoSaleByPerIds(id);
        }else {
            sessions = yanchuSessionMapper.getOnsaleByPerIds(Collections.singletonList(id));
        }
        if (CollectionUtils.isEmpty(sessions)){
            return perform;
        }
        List<Long> sessionIds = sessions.stream().map(YanchuSession::getId).distinct().collect(Collectors.toList());
        //获取演出价格区间
        List<SessionAndTicket> price = yanchuTicketPriceMapper.getPrice(Collections.singletonList(id),sessionIds);
        //时间区间
        List<SessionAndTicket> time = yanchuSessionMapper.getTime(Collections.singletonList(id), sessionIds);
        //剧场
        List<YanchuSession> hallName = yanchuSessionMapper.getHallName(Collections.singletonList(id), sessionIds);
        //获取实名标签
        List<Long> autType = yanchuSessionMapper.getAutType(Collections.singletonList(id),sessionIds);
        //获取电子票类标签
        List<Long> isTickets = yanchuSessionMapper.getIsTickets(Collections.singletonList(id),sessionIds);
        if (CollectionUtils.isNotEmpty(price)){
            perform.setMinPrice(price.get(0).getMinPrice());
            perform.setMaxPrice(price.get(0).getMaxPrice());
        }
        if (CollectionUtils.isNotEmpty(time)){
            perform.setStartTime(time.get(0).getStartTime());
            perform.setEndTime(time.get(0).getEndTime());
        }
        if (CollectionUtils.isNotEmpty(hallName)){
            perform.setHallName(hallName.get(0).getSessionName());
        }
        if (CollectionUtils.isNotEmpty(autType)){
            perform.setAutType(1);
        }else {
            perform.setAutType(2);
        }
        if (CollectionUtils.isNotEmpty(isTickets)){
            perform.setIsTickets(1);
        }else {
            perform.setIsTickets(2);
        }

        //评价数据
        EvaluateVo evaluateVo = evaluateMapper.getEvaluateData(perform.getId());
        if(null != evaluateVo){
            evaluateVo.setTotal(evaluateVo.getBetterEvaluate() + evaluateVo.getBadEvaluate());
            perform.setEvaluateVo(evaluateVo);
        }else {
            perform.setEvaluateVo(new EvaluateVo());
        }
        return perform;
    }
}
